<?php

namespace app\user\logic;

use app\common\exception\LogicException;
use app\model\AbnormalType;
use app\model\PigDailyEat;
use app\model\Pig;
use app\model\Abnormal;
use app\model\PigHealth;
use app\model\PigWeight;
use DateTime;
use think\db\Where;

class PigLogic
{
    /**
     * @Description 列表
     * @param array $param
     * @time 2023/09/04 10:39:31
     * @return mixed
     * @author: zj
     */
    public function getList(array $param)
    {
        $factoryId = request()->user_info['factory_id'];
        $pigModel = new Pig();
        $query = $pigModel->alias('p')
            ->leftJoin('factory fa', 'p.factory_id = fa.id')
            ->leftJoin('fence fe', 'p.out_fence_id = fe.out_id')
            ->leftJoin('barn b', 'fe.out_barn_id = b.out_id')
            ->field('p.out_id as id,p.factory_id,fa.name as factory,p.breed as breed_name,p.out_fence_id as fence_id,fe.name as fence,fe.out_barn_id as barn_id,b.name as barn,p.tag_address as ear_code,p.entry_time as in_time,p.exit_time as out_time,p.health as status,p.weight,p.record_time,p.create_time')
            ->where('p.factory_id', $factoryId)
            ->where('p.exit_time', $pigModel::IS_EXIT_NO)
            ->where('p.delete_time', $pigModel::IS_DELETE_NO);
        if ($param['fence_id']) {
            $query->where('p.out_fence_id', $param['fence_id']);
        }
        if ($param['barn_id']) {
            $query->where('fe.out_barn_id', $param['barn_id']);
        }
        if ($param['ear_code']) {
            $query->where('p.tag_address', $param['ear_code']);
        }
        if ($param['status']) {
            $query->where('p.health', $param['status']);
        } else {
            $query->where('p.health', 'in', [$pigModel::STATUS_HEALTH, $pigModel::STATUS_POTENTIAL_HEALTH, $pigModel::STATUS_SICK, $pigModel::STATUS_OBSERVATION, $pigModel::STATUS_INEFFECTIVE]);
        }
        if ($param['max_weight']) {
            $query->where('p.weight', '<=', $param['max_weight']);
        }
        if ($param['min_weight']) {
            $query->where('p.weight', '>=', $param['min_weight']);
        }
        if ($param['record_time_start']) {
            $query->where('p.record_time', '<=', $param['record_time_start']);
        }
        if ($param['record_time_end']) {
            $query->where('p.record_time', '>=', $param['record_time_end']);
        }
        // 入栏时间
        if ($param['in_time_start']) {
            $query->where('p.entry_time', '<=', $param['in_time_start']);
        }
        if ($param['in_time_end']) {
            $query->where('p.entry_time', '>=', $param['in_time_end']);
        }
        // 出栏时间
        if ($param['out_time_start']) {
            $query->where('p.exit_time', '<=', $param['out_time_start']);
        }
        if ($param['out_time_end']) {
            $query->where('p.exit_time', '>=', $param['out_time_end']);
        }

        $list = $query->order("p.out_id DESC")
            ->paginate([
                'list_rows' => $param['page_size'],
                'page' => $param['page']
            ])
            ->toArray();
        if ($list) {
            $pigWeightModel = new PigWeight();
            $eatModel = new PigDailyEat();
            $abnormalModel = new Abnormal();
            foreach ($list['data'] as $key => &$value) {
                // 猪异常病因
                $abnormal = [];
                if ($value['status'] != $pigModel::STATUS_HEALTH) {
                    $abnormal = $abnormalModel->alias('a')
                        ->join('abnormal_type at', 'a.sec_abnormal_type_id = at.out_id', 'left')
                        ->field('at.name as abnormal_type,a.error_text,a.solution,a.status')
                        ->where('factory_id', $factoryId)
                        ->where('case_id', $value['id'])
                        ->where('abnormal_type', AbnormalType::TYPE_PIG)
                        ->order('a.out_id DESC')
                        ->find();
                    if ($abnormal) {
                        $abnormal = $abnormal->toArray();
                    }
                }
                $value['abnormal'] = $abnormal;

                // 单猪的体重增量
                $weightGain = $pigWeightModel->checkWeightGain($value['id'], 0, time());
                // 单猪的进食量
                $foodIntake = $eatModel->checkFoodIntake($value['id'], 0, time());
                // 单猪 料肉比
                $ratio = 0;
                if ($weightGain != 0) {
                    $ratio = round($foodIntake / $weightGain, 2);
                }
                $value['weight_gain'] = $weightGain;
                $value['food_intake'] = $foodIntake;
                $value['ratio'] = $ratio;
            }
            unset($value);
        }

        return $list;
    }

    /**
     * @Description 详情
     * @param int $id
     * @time 2024/03/27 10:22:33
     * @return mixed
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * @author: zj
     */
    public function getDetail(int $id)
    {
        $factoryId = request()->user_info['factory_id'];
        $pigModel = new Pig();
        $query = $pigModel->alias('p')
            ->leftJoin("factory f", "f.id = p.factory_id")
            ->leftJoin("fence fe", "fe.id = p.out_fence_id")
            ->leftJoin("barn b", "b.id = fe.out_barn_id")
            ->where("p.out_id", $id)
            ->where("p.factory_id", $factoryId)
            ->where("p.delete_time", $pigModel::IS_DELETE_NO)
            ->field("p.out_id as id,p.factory_id,f.name as factory,fe.out_barn_id as barn_id,p.batch,b.name as building,p.out_fence_id as fence_id,fe.name as fence,p.breed as breed_name,p.tag_address as ear_code,p.entry_time as in_time,p.exit_time as out_time,p.health as status,p.weight,p.record_time,p.create_time");
        $info = $query->find();
        if (!$info) {
            throw new LogicException("猪不存在");
        }
        $info = $info->toArray();
        // 猪异常病因
        $abnormalModel = new Abnormal();

        $abnormal = [];
        if ($info['status'] != $pigModel::STATUS_HEALTH) {
            $abnormal = $abnormalModel->alias('a')
                ->join('abnormal_type at', 'a.sec_abnormal_type_id = at.out_id', 'left')
                ->field('at.name as abnormal_type,a.error_text,a.solution,a.status')
                ->where('factory_id', $factoryId)
                ->where('case_id', $info['id'])
                ->where('abnormal_type', AbnormalType::TYPE_PIG)
                ->order('out_id DESC')
                ->find();
            if ($abnormal) {
                $abnormal = $abnormal->toArray();
            }
        }

        $info['abnormal'] = $abnormal;
        // 入栏天数
        if ($info['out_time']) {
            $entryDays = ceil(($info['out_time'] + 1 - $info['in_time']) / 86400);
        } else {
            $entryDays = ceil((time() - $info['in_time']) / 86400);
        }
        $info['entry_days'] = (int)$entryDays;

        // 猪的最新健康数据
        $healthModel = new PigHealth();
        $health = $healthModel->lastHealthData($factoryId, $info['id']);
        $info['heartbeat'] = $health ? $health['heart_rate'] : 0;
        $info['breathe'] = $health ? $health['breathe'] : 0;
        $info['temperature'] = $health ? $health['temperature'] : 0;
        $info['blood_oxygen'] = $health ? $health['sao2'] : 0;
        $info['pi'] = $health ? $health['pi'] : 0;

        // 单猪的体重增量
        $pigWeightModel = new PigWeight();
        $weightGain = $pigWeightModel->checkWeightGain($id, 0, time());
        // 单猪的进食量
        $eatModel = new PigDailyEat();
        $foodIntake = $eatModel->checkFoodIntake($id, 0, time());
        // 料肉比
        $ratio = 0;
        if ($weightGain != 0) {
            $ratio = round($foodIntake / $weightGain, 2);
        }
        $info['weight_gain'] = $weightGain;
        $info['food_intake'] = $foodIntake; // 进食量
        $info['ratio'] = $ratio; // 料肉比

        return $info;
    }

    public function detailSupply(int $factoryId, int $pigId)
    {
        // 猪
        $pigModel = new Pig();
        $pig = $pigModel->field('id,ear_code')
            ->where('factory_id', $factoryId)
            ->where('id', $pigId)
            ->where('delete_time', $pigModel::IS_DELETE_NO)
            ->find();
        if (!$pig) {
            throw new LogicException("猪不存在");
        }
        $pig = $pig->toArray();

        // 前天
        $qtStartTime = strtotime(date("Y-m-d", strtotime("-2 day"))); // 前天起始时间戳
        $qtEndTime = $qtStartTime + 86399; // 前天结束时间戳
        // 昨天
        $yesterdayStartTime = strtotime(date("Y-m-d", strtotime("-1 day"))); // 昨天起始时间戳
        $yesterdayEndTime = $yesterdayStartTime + 86399; // 昨天结束时间戳

        $weightModel = new PigWeight();
        // 最新体重
        $lastWeight = $weightModel->getLastWeight($pigId);
        // 昨天最新体重
        $yesterdayLastWeight = $weightModel->getLastWeight($pigId, $yesterdayEndTime);

        if ($yesterdayLastWeight < $lastWeight) {
            $weightChange = "improve";
        } elseif ($yesterdayLastWeight > $lastWeight) {
            $weightChange = "reduce";
        } else {
            $weightChange = "unchanged";
        }

        $eatModel = new PigDailyEat();
        $ratio1 = 0;
        $ratio2 = 0;
        // 前天猪的进食量
        $foodIntake1 = $eatModel->checkFoodIntake($pig['id'], $qtStartTime, $qtEndTime);
        // 前天猪的体重增量
        $weightGain1 = $weightModel->checkWeightGain($pig['id'], $qtStartTime, $qtEndTime);
        if ($weightGain1 != 0) {
            $ratio1 = round($foodIntake1 / $weightGain1, 2);
        }
        // 昨天猪的进食量
        $foodIntake2 = $eatModel->checkFoodIntake($pig['id'], $yesterdayStartTime, $yesterdayEndTime);
        // 昨天猪的体重增量
        $weightGain2 = $weightModel->checkWeightGain($pig['id'], $yesterdayStartTime, $yesterdayEndTime);
        if ($weightGain2 != 0) {
            $ratio2 = round($foodIntake2 / $weightGain2, 2);
        }

        if ($ratio1 < $ratio2) {
            $ratioChange = "improve";
        } elseif ($ratio1 > $ratio2) {
            $ratioChange = "reduce";
        } else {
            $ratioChange = "unchanged";
        }

        return [
            'weight_change' => $weightChange,
            'ratio_change' => $ratioChange
        ];
    }

    /**
     * @Description 猪的下拉选择列表
     * @param array $param
     * @time 2023/09/11 18:35:36
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     * @author: zj
     */
    public function selectList(array $param)
    {
        $factoryId = request()->user_info['factory_id'];

        $pigModel = new Pig();
        $query = $pigModel->field('out_id as id,tag_address as ear_code')
            ->where('factory_id', $factoryId)
            ->where('out_fence_id', $param['fence_id'])
            ->where('exit_time', $pigModel::IS_EXIT_NO)
            ->where('delete_time', $pigModel::IS_DELETE_NO);
        if ($param['ear_code']) {
            $query->where('tag_address', 'like', '%' . trim($param['ear_code']) . '%');
        }
        return $query->order('out_id ASC')
            ->paginate([
                'list_rows' => $param['page_size'],
                'page' => $param['page']
            ])
            ->toArray();
    }

    public function inOut(int $factoryId, array $param)
    {
        $keyMonthLogic = new KeyMonthArrLogic();
        $returnData = $keyMonthLogic->getArr($param['start_month'], $param['end_month']);

        $startTime = strtotime($param['start_month']);
        $endTime = strtotime('+1 month', strtotime($param['end_month'])) - 1;

        $pigModel = new Pig();
        //入栏查询
        $inQuery = $pigModel
            ->field('date_format(from_unixtime(in_time), "%Y-%m") month, count(*) as total_pig')
            ->where('factory_id', $factoryId)
            ->where('in_time', '>=', $startTime)
            ->where('in_time', '<=', $endTime)
            ->where('delete_time', $pigModel::IS_DELETE_NO);

        //出栏查询
        $outQuery = $pigModel
            ->field('date_format(from_unixtime(out_time), "%Y-%m") month, count(*) as total_pig')
            ->where('factory_id', $factoryId)
            ->where('out_time', '>=', $startTime)
            ->where('out_time', '<=', $endTime)
            ->where('delete_time', $pigModel::IS_DELETE_NO);

        //筛选栏
        if ($param['fence_id']) {
            $inQuery->where('fence_id', $param['fence_id']);
            $outQuery->where('fence_id', $param['fence_id']);
        }

        //入栏数据
        $inData = $inQuery->group('month')
            ->select()
            ->toArray();
        if ($inData) {
            foreach ($inData as $v) {
                $returnData[$v['month']]['in'] = $v['total_pig'];
            }
        }

        //出栏数据
        $outData = $outQuery->group('month')
            ->select()
            ->toArray();
        if ($outData) {
            foreach ($outData as $v) {
                $returnData[$v['month']]['out'] = $v['total_pig'];
            }
        }

        return $returnData;
    }

    /**
     * @Description 健康统计
     * @param $param
     * @time 2024/03/20 17:01:52
     * @return array
     * @author: zj
     */
    public function healthStatistic($param)
    {
        $factoryId = request()->user_info['factory_id'];

        $model = new Pig();
        $healthCount = $model->checkPigCount($factoryId, $param['barn_id'], $param['fence_id'], $model::STATUS_HEALTH);
        $PotentialHealthCount = $model->checkPigCount($factoryId, $param['barn_id'], $param['fence_id'], $model::STATUS_POTENTIAL_HEALTH);
        $sickCount = $model->checkPigCount($factoryId, $param['barn_id'], $param['fence_id'], $model::STATUS_SICK);
        $underObservationCount = $model->checkPigCount($factoryId, $param['barn_id'], $param['fence_id'], $model::STATUS_OBSERVATION);
        $treatmentIneffectiveCount = $model->checkPigCount($factoryId, $param['barn_id'], $param['fence_id'], $model::STATUS_INEFFECTIVE);
        $deadCount = $model->checkPigCount($factoryId, $param['barn_id'], $param['fence_id'], $model::STATUS_DEAD);

        return [
            'health_count' => $healthCount,
            'potential_health_count' => $PotentialHealthCount,
            'sick_count' => $sickCount,
            'under_observation_count' => $underObservationCount,
            'treatment_ineffective_count' => $treatmentIneffectiveCount,
            'dead_count' => $deadCount,
        ];
    }

    /**
     * @Description 食谱中心 -- 生猪列表
     * @author: zj
     * @param array $param
     * @time 2024/03/27 10:57:05
     * @return mixed
     */
    public function useCookBookBarn(array $param)
    {
        $factoryId = request()->user_info['factory_id'];

        $model = new Pig();
        $query = $model->alias('p')
            ->join('fourteen_feed_plan ffp', 'ffp.out_id = p.feed_plan_id', 'left')
            ->field('p.out_id as id,p.tag_address,ffp.name as feed_plan')
            ->where('p.factory_id', $factoryId)
            ->where('p.delete_time', $model::IS_DELETE_NO);
        if ($param['barn_id']) {
            $query->whereOr('p.out_barn_id', $param['barn_id']);
        }
        if ($param['fence_id']) {
            $query->whereOr('p.out_fence_id', $param['fence_id']);
        }

        return $query->order('p.out_id DESC')
            ->paginate([
                'list_rows' => $param['page_size'],
                'page' => $param['page']
            ])
            ->toArray();
    }

}